#include "fuc_optical.h"
#include "bsp_usart.h"

 /**
  * @brief  高级控制定时器TIMx,x[1,8]中断优先级配置
  * @param  无
  * @retval 无
  */
static void TIMx_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  //设置中断组为0
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);	
  //设置中断源
  NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQn; 	
  //设置抢占优先级
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  //设置子优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

static void TimeBaseInit_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  /*--------------------时基结构体初始化----------------------*/
  TIM_TimeBaseStructure.TIM_Period = ADVANCE_TIM_PERIOD;//累计TIM_Period个周期后产生一个更新或中断
  TIM_TimeBaseStructure.TIM_Prescaler = ADVANCE_TIM_PSC;//驱动计数器的时钟 = TIMxCLK/(psc+1)
  TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频因子，配置死区时间时需要用到
  TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数方式
  TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//重复计数器的值，没有用到不用管它
  TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);//初始化定时器
}

static void TIM_ICInitStructure(void)
{
  TIM_ICInitTypeDef  TIM_ICInitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);  
  /*--------------------输入捕获结构体初始化----------------------*/
  //使用PWM输入模式时，需要占用两个捕获寄存器，一个测量周期，另外一个测占空比
  //捕获通道IC1配置
  TIM_ICInitStructure.TIM_Channel = ADVANCE_IC1PWM_CHANNEL;//选择捕获通道
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//设置上升沿捕获
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//设置捕获通道的信号来自于哪个输入通道，有直连和非直连两种
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//1分频，即捕获信号的每个有效边沿都捕获
  TIM_ICInitStructure.TIM_ICFilter = 0x0;//不滤波
  TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure);//初始化PWM输入模式
  //当工作在PWM输入模式时，只需要设置触发信号的那一路即可（用于测量周期），另外一路（用于测量占空比）会由硬件自动配置。
  TIM_SelectInputTrigger(ADVANCE_TIM, TIM_TS_TI1FP1);//选择输入捕获的触发信号
  TIM_SelectSlaveMode(ADVANCE_TIM, TIM_SlaveMode_Reset);//选择从模式：复位模式
  TIM_SelectMasterSlaveMode(ADVANCE_TIM,TIM_MasterSlaveMode_Enable);//PWM输入模式时，从模式必须工作在复位模式，当捕获开始时，计数器CNT会被复位
  TIM_ITConfig(ADVANCE_TIM, TIM_IT_CC1, ENABLE);//使能捕获中断，这个中断针对的是主捕获通道（测量周期那个）
	TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);//清除中断标志位
}

static void GPIO_InitStructure(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd (ADVANCE_ICPWM_GPIO_CLK, ENABLE);
  GPIO_PinAFConfig(ADVANCE_ICPWM_GPIO_PORT,ADVANCE_ICPWM_PINSOURCE,ADVANCE_ICPWM_AF);//定时器复用引脚
	GPIO_InitStructure.GPIO_Pin = ADVANCE_ICPWM_PIN;//高级定时器PWM输入捕获引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(ADVANCE_ICPWM_GPIO_PORT, &GPIO_InitStructure);
}

//高速脉冲读取时需要注意，初始化部分的顺序
void TIM_PWMINPUT_Config(void)
{
  GPIO_InitStructure();
	TimeBaseInit_Config();
	TIM_ICInitStructure();
	TIMx_NVIC_Config();
	TIM_Cmd(ADVANCE_TIM, ENABLE);//使能高级控制定时器，计数器开始计数
}

/************************** 中断服务函数 **********************************/
extern uint16_t IC2Value;
extern uint16_t IC1Value;
extern float DutyCycle;
extern float Frequency;
extern uint16_t count;
void  ADVANCE_TIM_IRQHandler (void)
{
  /* 清除定时器捕获/比较中断 */
  TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);
  /* 获取输入捕获值 */
  IC1Value = TIM_GetCapture1(ADVANCE_TIM);
  IC2Value = TIM_GetCapture2(ADVANCE_TIM);	
  // 注意：捕获寄存器CCR1和CCR2的值在计算占空比和频率的时候必须加1
	if (IC1Value != 0)
  {
    /* 占空比计算 */
		count++;
    DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);
    /* 频率计算 */
    Frequency = 168000000/(ADVANCE_TIM_PSC+1)/(float)(IC1Value+1);
		printf("ocupyScale:%0.2f%%   frequency:%0.2fHz\r\n",DutyCycle,Frequency);
	}
	else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}
